﻿module Sustainalytics.Navigation {

    import Common = Sustainalytics.Common;

    export class NavigationService implements INavigationService {

        private siteMaps: Common.Dictionary<SiteMap>;

        constructor(
            private $q: ng.IQService,
            private $rootScope: ng.IScope,
            private $routeParams: ng.route.IRouteParamsService,
            private $route: ng.route.IRouteService,
            private SiteMapNodeRouteResolverService: ISiteMapNodeRouteResolverService) {

            var ctx = this;

            ctx.siteMaps = new Common.Dictionary<SiteMap>();

            // listend for route changes
            ctx.initSiteMapRouteChanged();
        }

        private initSiteMapRouteChanged() {
            var ctx = this;

            // when the route changes maintain all sitemaps
            ctx.$rootScope.$on('$routeChangeSuccess', function () {

                ctx.updateSiteMaps();
            });
        }

        public updateSiteMaps(): ng.IPromise<any> {
            var ctx = this;

            // get current path
            var path = ctx.getCurrentPath();

            var updatePromiseLst = [];

            // for each site map re-evaluate nodes
            ctx.siteMaps.getValues().forEach(function (siteMap) {

                var updatePromise = ctx.updateSiteMap(path, siteMap);

                updatePromiseLst.push(updatePromise);
            });

            return ctx.$q.all(updatePromiseLst).then(function () {
                // notify that navigation has changed
                ctx.$rootScope.$broadcast('navigationSitemapChanged');
            });            
        }

        private updateSiteMap(path: string, siteMap: SiteMap): ng.IPromise<any> {

            // select nodes
            var selectedNodes = siteMap.selectNodes(path);

            // evaluate node routes
            var evalNodesPromise = siteMap.evalSpecificNodeRoutes(selectedNodes);

            return evalNodesPromise;
        }

        private getCurrentPath(): string {
            var ctx = this;

            if (!ctx.$route.current || !ctx.$route.current['$$route'])
                return '/';

            // get current path
            var path = ctx.$route.current['$$route'].originalPath;

            return path;
        }

        public addSiteMapNode(siteMapCode: string, parentCode: string, order: number, siteMapNodes: ISiteMapNode[]): NavigationService {
            var ctx = this;

            // get site map
            var siteMap: SiteMap = ctx.getSiteMap(siteMapCode);

            // add nodes
            siteMap.addNodes(siteMapNodes, parentCode, order);

            return ctx;
        }

        public getSiteMap(siteMapCode: string): SiteMap {
            var ctx = this;

            var siteMap: SiteMap;

            // get site map
            if (ctx.siteMaps.containsKey(siteMapCode)) {
                siteMap = ctx.siteMaps.getValue(siteMapCode);
            }
            else {
                siteMap = new SiteMap(ctx.$q, ctx.SiteMapNodeRouteResolverService);
                ctx.siteMaps.add(siteMapCode, siteMap);
            }

            return siteMap;
        }
    }


    export var navigationServiceName = 'NavigationService';

    angular.module(navigationModuleName).service(navigationServiceName, NavigationService);
} 